﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using fleXdoc.ServiceClient.Proxy;
using System.IO;
using System.IO.IsolatedStorage;
using System.Globalization;
using System.Diagnostics;
using System.Threading;

namespace fleXdoc.ServiceClient
{
    public partial class frmMain : Form
    {
        private IConfigManager _configMgr; // Instantiated in Load-event

        public frmMain()
        {
            InitializeComponent();
        }

        private void btnBrowseDataXMLFile_Click(object sender, EventArgs e)
        {
            dlgOpenFile.FileName = txtDataXmlFile.Text;
            if (dlgOpenFile.ShowDialog(this) == DialogResult.OK)
            {
                txtDataXmlFile.Text = dlgOpenFile.FileName;
            }
        }

        private void InvokeOnUIThreadIfRequired(Control ctrl, MethodInvoker method)
        {
            if (ctrl.InvokeRequired)
            {
                ctrl.Invoke(method);
            }
            else
            {
                method();
            }
        }

        private DocumentBuilderClient GetDocBuilderClient(string endpointBase, bool useMTOM)
        {
            string endpointName = (useMTOM ? "mtom" : "text");
            string remoteAddress = endpointBase + "/" + (useMTOM ? "mtom" : "text");
            DocumentBuilderClient client = new DocumentBuilderClient(endpointName, remoteAddress);
            return client;
        }

        private void btnBuild_Click(object sender, EventArgs e)
        {
            btnBuild.Enabled = false;
            lblDocLink.Visible = false;

            DocumentBuilderClient client = GetDocBuilderClient(txtEndpointBase.Text, rdMTOM.Checked);
            
            Stream outputStream = null;

            try
            {
                InvokeOnUIThreadIfRequired(this, delegate() { lblStatus.Text = "Invoking service..."; });
                Application.DoEvents();
                client.Open();
                BuildDocumentRequest request = new BuildDocumentRequest();
                request.Username = Thread.CurrentPrincipal.Identity.Name;
                request.Template = txtTemplate.Text;
                request.dataXML = File.ReadAllText(txtDataXmlFile.Text, Encoding.UTF8);
                request.RenderCulture = txtCulture.Text;
                request.Validation = cbValidation.Checked ? BuildValidation.Enabled : BuildValidation.Disabled;
                outputStream = client.BuildDocument(request);
                
                // Copy the stream to a file on disc
                string tempFilename = Path.GetRandomFileName() + ".docx";
                string tempFile = Path.Combine(txtOutputFolder.Text, tempFilename);
                using (MemoryStream document = new MemoryStream())
                {
                    IOHelper.CopyStream(outputStream, document);
                    outputStream.Close();
                    File.WriteAllBytes(tempFile, document.ToArray());
                    long filesizeKB = document.Length / 1024;
                    lblDocLink.Tag = tempFile; // So the event can find the filename
                    lblDocLink.Text = String.Format(CultureInfo.InvariantCulture, "Last built document ({0} KB)", filesizeKB);
                    lblDocLink.Visible = true;
                }

                // Open the file with Word
                if (cbOpenAfterBuild.Checked)
                {
                    InvokeOnUIThreadIfRequired(this, delegate() { lblStatus.Text = "Success. Opening document..."; });
                    Application.DoEvents();
                    OpenDoc(tempFile);
                }
                InvokeOnUIThreadIfRequired(this, delegate() { lblStatus.Text = "Ready"; });
            }
            catch (System.ServiceModel.FaultException<Exception> faultEx)
            {
                lblStatus.Text = "Build Error: " + faultEx.Detail.Message;
                MessageBox.Show(this, faultEx.Detail.Message, "Build Error", MessageBoxButtons.OK);
            }
            catch (Exception ex)
            {
                lblStatus.Text = "Error: " + ex.Message;
                MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK);
            }
            finally
            {
                if (outputStream != null)
                {
                    outputStream.Close();
                }
                CleanupDocBuilderClient(client);
                btnBuild.Enabled = true;
            }
        }

        private void CleanupDocBuilderClient(DocumentBuilderClient client)
        {
            if (client.State == System.ServiceModel.CommunicationState.Opened)
            {
                client.Close();
            }
        }

        private void OpenDoc(string tempFilename)
        {
            Process proc = new Process();
            proc.StartInfo = new ProcessStartInfo(tempFilename);
            proc.Start();
        }

        private void btnBrowseOutputFolder_Click(object sender, EventArgs e)
        {
            dlgOpenFolder.SelectedPath = txtOutputFolder.Text;
            if (dlgOpenFolder.ShowDialog(this) == DialogResult.OK)
            {
                txtOutputFolder.Text = dlgOpenFolder.SelectedPath;
            }
        }

        private void lblDocLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            InvokeOnUIThreadIfRequired(this, delegate() { lblStatus.Text = "Opening document..."; });
            Application.DoEvents();
            try
            {
                OpenDoc((string)((sender as LinkLabel).Tag));
                InvokeOnUIThreadIfRequired(this, delegate() { lblStatus.Text = "Ready"; });
            }
            catch (Exception ex)
            {
                lblStatus.Text = "Error: " + ex.Message;
                MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK);
            }
        }

        private void btnRetrieve_Click(object sender, EventArgs e)
        {
        //    this.Cursor = Cursors.WaitCursor;
        //    InvokeOnUIThreadIfRequired(this, delegate() { lblStatus.Text = "Retrieving list of supported output formats..."; });
        //    Application.DoEvents();

        //    DocumentBuilderClient client = GetDocBuilderClient(txtEndpointBase.Text, rdMTOM.Checked);

        //    try
        //    {
        //        client.Open();
        //        SupportedOutputFormats formats = client.GetSupportedOutputFormats();

        //        comboOutputFormat.Items.Clear();
        //        foreach (string format in formats)
        //        {
        //            comboOutputFormat.Items.Add(format);
        //        }

        //        if (formats.Count > 0)
        //        {
        //            // Select first
        //            comboOutputFormat.SelectedIndex = 0;
        //        }
        //        else
        //        {
        //            comboOutputFormat.SelectedItem = null;
        //        }
        //    }
        //    finally
        //    {
        //        this.Cursor = Cursors.Default;
        //        InvokeOnUIThreadIfRequired(this, delegate() { lblStatus.Text = "Ready"; });
        //        Application.DoEvents();

        //        CleanupDocBuilderClient(client);
        //    }
        }

        private void BindConfig()
        {
            txtTemplate.Text = _configMgr.Config.Template;
            txtCulture.Text = _configMgr.Config.RenderCulture;
            txtDataXmlFile.Text = _configMgr.Config.DataFilePath;
            txtOutputFolder.Text = _configMgr.Config.OutputPath;
            cbValidation.Checked = _configMgr.Config.Validate;
            txtEndpointBase.Text = _configMgr.Config.EndpointAddressBase;
            comboOutputFormat.Text = _configMgr.Config.OutputFormat;
            rdMTOM.Checked = _configMgr.Config.MTOM;
            rdText.Checked = !_configMgr.Config.MTOM;
        }

        private void UnbindConfig()
        {
            _configMgr.Config.Template = txtTemplate.Text;
            _configMgr.Config.RenderCulture = txtCulture.Text;
            _configMgr.Config.DataFilePath = txtDataXmlFile.Text;
            _configMgr.Config.OutputPath = txtOutputFolder.Text;
            _configMgr.Config.Validate = cbValidation.Checked;
            _configMgr.Config.EndpointAddressBase = txtEndpointBase.Text;
            _configMgr.Config.MTOM = rdMTOM.Checked;
            _configMgr.Config.OutputFormat = comboOutputFormat.Text;
        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            // Load config and bind UI
            _configMgr = new RegistryConfigManager();
            _configMgr.Load();
            BindConfig();
        }

        private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            UnbindConfig();
            _configMgr.Save();
        }

        private void btnDefaultSettings_Click(object sender, EventArgs e)
        {
            _configMgr.ResetDefaults();
            BindConfig();
        }

    }
}
